package com.dkha.common.util;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author Spring
 * @Since 2019/12/11 14:24
 * @Description 基于jackson 对象序列化反序列化工具
 */

public class JsonUtil {

    private static Logger logger = LoggerFactory.getLogger(JsonUtil.class);

    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        //序列化的时候序列对象的所有属性
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);

        // 如果是空对象的时候,不抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //属性为null的转换--为空的值不参与反序列化
        //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 取消默认转换timestamps对象
        objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
        // 所有日期统一格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        // 忽略 在json字符串中存在, 但是在java对象中不存在对应属性的情况, 防止出错
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }


    public static <T> String obj2String(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper
                    .writeValueAsString
                            (obj);
        } catch (Exception e) {
            logger.error("Parse object to String error:" + e);
            return null;
        }
    }

    /**
     * 返回一个格式化好的字符串, 用于调试
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String obj2StringPretty(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper.writerWithDefaultPrettyPrinter()
                    .writeValueAsString
                            (obj);
        } catch (Exception e) {
            logger.error("Parse object to String error:" + e);
            return null;
        }
    }

    /**
     * 将字符串转成对象, 单个
     * @param str
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T string2Obj(String str, Class<T> clazz) {
        if (UtilValidate.isEmpty(str) || clazz == null) {
            return null;
        }
        try {
            return clazz.equals(String.class) ? (T)str : objectMapper.readValue
                    (str, clazz);
        } catch (IOException e) {
            logger.error("Parse String to Object error :" + e);
            return null;
        }
    }

    /**
     * 将字符串转换成对象, 集合
     * List<SysUserEntity> userEntityList1 = JsonUtil.string2Obj(str, new TypeReference<List<SysUserEntity>>() {});
     * @param str
     * @param typeReference
     * @param <T>
     * @return
     */
    public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
        if (UtilValidate.isEmpty(str) || typeReference == null) {
            return null;
        }
        try {
            return (T)(typeReference.getType().equals(String.class) ? (T)str :
                    objectMapper.readValue
                            (str, typeReference));
        } catch (IOException e) {
            logger.error("Parse String to typeReference Object error :" + e);
            return null;
        }
    }
    /**
     * 将字符串转换成对象, 集合
     *  List<SysUserEntity> sysUserEntityList2 = JsonUtil.string2Obj(str, List.class, SysUserEntity.class);
     * @param str
     * @param collectionClass
     * @param <T>
     * @return
     */
    public static <T> T string2Obj(String str, Class<?> collectionClass, Class<?>... elementClasses) {
        JavaType javaType = objectMapper.getTypeFactory()
                .constructParametricType(collectionClass, elementClasses);
        try {
            return objectMapper.readValue(str, javaType);
        } catch (IOException e) {
            logger.error("Parse String to Object2 error :" + e);
            return null;
        }
    }

    /**
     * 测试代码
     */
    public static void main(String[] args) {
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setUsername("张三");
        userEntity.setCreateTime(new Date());
        System.out.println(JsonUtil.obj2String(userEntity));
        List<SysUserEntity> userEntityList = new ArrayList<>();
        userEntityList.add(userEntity);
        System.out.println(JsonUtil.obj2String(userEntityList));

        String str = "[{\"username\":\"张三\",\"createTime\":\"2019-12-11 14:38:01\"}, {\"username\":\"李四\",\"createTime\":\"2019-10-11 14:38:01\"}]";
        List<SysUserEntity> userEntityList1 = JsonUtil.string2Obj(str, new TypeReference<List<SysUserEntity>>() {
        });
        System.out.println(userEntityList1.toString());

        List<SysUserEntity> sysUserEntityList2 = JsonUtil.string2Obj(str, List.class, SysUserEntity.class);
        System.out.println(sysUserEntityList2.toString());

        SysUserEntity userEntity1 = JsonUtil.string2Obj("", SysUserEntity.class);
    }

    @Data
    public static class SysUserEntity  {
        private static final long serialVersionUID = 1L;
        /**
         * 用户名
         */
        private String username;
        /**
         * 密码
         */
        private String password;
        /**
         * 姓名
         */
        private String realName;
        /**
         * 头像
         */
        private String headUrl;
        /**
         * 性别   0：男   1：女    2：保密
         */
        private Integer gender;
        /**
         * 邮箱
         */
        private String email;
        /**
         * 手机号
         */
        private String mobile;
        /**
         * 部门ID
         */
        private Long deptId;
        /**
         * 超级管理员   0：否   1：是
         */
        private Integer superAdmin;
        /**
         * 状态  0：停用   1：正常
         */
        private Integer status;
        /**
         * 更新者
         */
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private Long updater;
        /**
         * 更新时间
         */
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private Date updateDate;
        /**
         * 部门名称
         */
        @TableField(exist=false)
        private String deptName;

        private Date createTime;
    }
}
